package utils

import (
	"context"
	"crypto/md5"
	"crypto/rand"
	"encoding/hex"
	"encoding/xml"
	"fmt"
	"sort"
	"strings"
	"time"

	"supershare/backend/models"

	"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/response"
	"github.com/ArtisanCloud/PowerWeChat/v3/src/payment"
	"github.com/ArtisanCloud/PowerWeChat/v3/src/payment/order/request"
	refund "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/refund/request"
	"github.com/beego/beego/v2/core/logs"
	"github.com/beego/beego/v2/server/web"
)

// WxPayConfig 微信支付配置
type WxPayConfig struct {
	AppID        string // 小程序ID
	MchID        string // 商户号
	Key          string // 商户密钥
	NotifyURL    string // 支付回调地址
	CertSerialNo string // 证书序列号
	CertPath     string // 证书路径
	KeyPath      string // 证书密钥路径
}

// WxPayNotifyData 微信支付回调数据结构
type WxPayNotifyData struct {
	ReturnCode         string `xml:"return_code"`          // 返回状态码
	ReturnMsg          string `xml:"return_msg"`           // 返回信息
	AppId              string `xml:"appid"`                // 公众账号ID
	MchId              string `xml:"mch_id"`               // 商户号
	NonceStr           string `xml:"nonce_str"`            // 随机字符串
	Sign               string `xml:"sign"`                 // 签名
	ResultCode         string `xml:"result_code"`          // 业务结果
	ErrCode            string `xml:"err_code"`             // 错误代码
	ErrCodeDes         string `xml:"err_code_des"`         // 错误代码描述
	OpenId             string `xml:"openid"`               // 用户标识
	IsSubscribe        string `xml:"is_subscribe"`         // 是否关注公众账号
	TradeType          string `xml:"trade_type"`           // 交易类型
	BankType           string `xml:"bank_type"`            // 付款银行
	TotalFee           int    `xml:"total_fee"`            // 订单金额
	SettlementTotalFee int    `xml:"settlement_total_fee"` // 应结订单金额
	FeeType            string `xml:"fee_type"`             // 货币种类
	CashFee            int    `xml:"cash_fee"`             // 现金支付金额
	CashFeeType        string `xml:"cash_fee_type"`        // 现金支付货币类型
	TransactionId      string `xml:"transaction_id"`       // 微信支付订单号
	OutTradeNo         string `xml:"out_trade_no"`         // 商户订单号
	Attach             string `xml:"attach"`               // 附加数据
	TimeEnd            string `xml:"time_end"`             // 支付完成时间
}

// WxPayParams 微信支付参数
type WxPayParams struct {
	AppID     string `json:"appId"`
	TimeStamp string `json:"timeStamp"`
	NonceStr  string `json:"nonceStr"`
	Package   string `json:"package"`
	SignType  string `json:"signType"`
	PaySign   string `json:"paySign"`
}

// PowerWeChatPayment 全局支付实例缓存
var paymentInstances = make(map[int64]*payment.Payment)

// getWxPayConfig 从数据库获取微信支付配置
func getWxPayConfig(franchiseId int64) (*WxPayConfig, error) {
	// 获取小程序配置
	config, err := models.GetMiniprogramConfigByFranchiseId(franchiseId)
	if err != nil {
		return nil, fmt.Errorf("获取小程序配置失败: %v", err)
	}

	// 检查必要的配置项
	if config.AppID == "" {
		return nil, fmt.Errorf("小程序AppID未配置")
	}
	if config.MchId == "" {
		return nil, fmt.Errorf("商户号未配置")
	}
	if config.MchKey == "" {
		return nil, fmt.Errorf("商户密钥未配置")
	}
	if config.NotifyUrl == "" {
		return nil, fmt.Errorf("支付回调地址未配置")
	}

	return &WxPayConfig{
		AppID:        config.AppID,
		MchID:        config.MchId,
		Key:          config.MchKey,
		NotifyURL:    config.NotifyUrl,
		CertSerialNo: config.CertSerialNo,
		CertPath:     config.CertFile,
		KeyPath:      config.KeyFile,
	}, nil
}

// getPowerWeChatPayment 获取PowerWeChat支付实例
func getPowerWeChatPayment(franchiseId int64) (*payment.Payment, error) {
	// 检查缓存
	if paymentInstance, exists := paymentInstances[franchiseId]; exists {
		return paymentInstance, nil
	}

	// 获取配置
	config, err := getWxPayConfig(franchiseId)
	if err != nil {
		return nil, err
	}
	wxpaycertpath := web.AppConfig.DefaultString("wxpaycertpath", "")
	// 创建PowerWeChat配置
	paymentConfig := &payment.UserConfig{
		AppID:              config.AppID,
		MchID:              config.MchID,
		MchApiV3Key:        config.Key,
		Key:                "",
		CertPath:           wxpaycertpath + config.CertPath,
		KeyPath:            wxpaycertpath + config.KeyPath,
		SerialNo:           config.CertSerialNo,
		CertificateKeyPath: "",
		WechatPaySerial:    config.CertSerialNo,
		NotifyURL:          config.NotifyURL,
		HttpDebug:          true,
		ResponseType:       response.TYPE_MAP,
		Log: payment.Log{
			Level: "debug",
		},
		Debug:   false,
		Sandbox: false, // 生产环境设为false
	}
	logs.Debug("PowerWeChat配置: %#v", paymentConfig)
	// 创建支付实例
	paymentApp, err := payment.NewPayment(paymentConfig)
	if err != nil {
		return nil, fmt.Errorf("创建PowerWeChat支付实例失败: %v", err)
	}

	// 缓存实例
	paymentInstances[franchiseId] = paymentApp

	return paymentApp, nil
}

// GenerateWxPayParams 生成微信支付参数 - 使用PowerWeChat SDK
func GenerateWxPayParams(franchiseId int64, orderNo string, totalFee int64, description string, openId string) (any, error) {
	// 获取PowerWeChat支付实例
	paymentApp, err := getPowerWeChatPayment(franchiseId)
	if err != nil {
		return nil, fmt.Errorf("PowerWeChat初始化失败: %v", err)
	}

	// 获取配置
	config, err := getWxPayConfig(franchiseId)
	if err != nil {
		return nil, err
	}

	// 创建统一下单请求参数
	params := &request.RequestJSAPIPrepay{
		PrepayBase: request.PrepayBase{
			AppID:     config.AppID,
			MchID:     config.MchID,
			NotifyUrl: config.NotifyURL,
		},
		Description: description,
		OutTradeNo:  orderNo,
		Amount: &request.JSAPIAmount{
			Total:    int(totalFee),
			Currency: "CNY",
		},
		Payer: &request.JSAPIPayer{
			OpenID: openId,
		},
	}

	ctx := context.Background()

	// 调用PowerWeChat统一下单接口
	result, err := paymentApp.Order.JSAPITransaction(ctx, params)
	if err != nil {
		return nil, fmt.Errorf("PowerWeChat统一下单失败: %v", err)
	}

	// 检查返回结果
	if result == nil {
		return nil, fmt.Errorf("PowerWeChat统一下单返回结果为空")
	}

	// 获取预支付ID
	if result.PrepayID == "" {
		return nil, fmt.Errorf("获取预支付ID失败")
	}

	payConf, err := paymentApp.JSSDK.BridgeConfig(result.PrepayID, false)
	if err != nil {
		return nil, fmt.Errorf("PowerWeChat获取JSSDK BridgeConfig失败: %v", err)
	}

	if payConf == nil {
		return nil, fmt.Errorf("PowerWeChat获取JSSDK BridgeConfig失败")
	}

	logs.Debug("PowerWeChat支付配置生成成功: %v", payConf)
	return payConf, nil
}

// ParseWxPayNotify 解析微信支付回调数据
func ParseWxPayNotify(body []byte) (*WxPayNotifyData, error) {
	var notifyData WxPayNotifyData
	err := xml.Unmarshal(body, &notifyData)
	if err != nil {
		return nil, err
	}
	return &notifyData, nil
}

// VerifyWxPayNotify 验证微信支付回调签名
func VerifyWxPayNotify(franchiseId int64, body []byte) (map[string]string, error) {
	// 获取微信支付配置
	config, err := getWxPayConfig(franchiseId)
	if err != nil {
		return nil, err
	}

	// 解析XML数据
	var notifyData map[string]string
	err = xml.Unmarshal(body, &notifyData)
	if err != nil {
		return nil, err
	}

	// 验证签名
	sign := notifyData["sign"]
	delete(notifyData, "sign")
	if generateSign(notifyData, config.Key) != sign {
		return nil, fmt.Errorf("签名验证失败")
	}

	// 验证支付结果
	if notifyData["return_code"] != "SUCCESS" || notifyData["result_code"] != "SUCCESS" {
		return nil, fmt.Errorf("支付失败: %s", notifyData["return_msg"])
	}

	return notifyData, nil
}

// GenerateWxPayNotifyResponse 生成微信支付回调响应
func GenerateWxPayNotifyResponse(returnCode, returnMsg string) string {
	response := struct {
		ReturnCode string `xml:"return_code"`
		ReturnMsg  string `xml:"return_msg"`
	}{
		ReturnCode: returnCode,
		ReturnMsg:  returnMsg,
	}

	xmlData, err := xml.Marshal(response)
	if err != nil {
		return ""
	}
	return string(xmlData)
}

// GetWxPayConfig 获取微信支付配置
func GetWxPayConfig(franchiseId int64) (*WxPayConfig, error) {
	return getWxPayConfig(franchiseId)
}

// generateSign 生成签名
func generateSign(params interface{}, key string) string {
	// 将参数转换为map
	var paramMap map[string]string
	switch v := params.(type) {
	case map[string]string:
		paramMap = v
	default:
		return ""
	}

	// 按键排序
	var keys []string
	for k := range paramMap {
		if k != "sign" && paramMap[k] != "" {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)

	// 拼接参数
	var builder strings.Builder
	for _, k := range keys {
		builder.WriteString(k)
		builder.WriteString("=")
		builder.WriteString(paramMap[k])
		builder.WriteString("&")
	}
	builder.WriteString("key=")
	builder.WriteString(key)

	// MD5加密
	hash := md5.New()
	hash.Write([]byte(builder.String()))
	return strings.ToUpper(hex.EncodeToString(hash.Sum(nil)))
}

// RandomString 生成随机字符串
func RandomString(n int) string {
	const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, n)
	if _, err := rand.Read(b); err != nil {
		return ""
	}
	for i := range b {
		b[i] = letters[int(b[i])%len(letters)]
	}
	return string(b)
}

// 生成随机字符串
func generateNonceStr() string {
	return fmt.Sprintf("%d", time.Now().UnixNano())
}

// 将map转换为XML
func mapToXML(params map[string]string) string {
	var builder strings.Builder
	builder.WriteString("<xml>")
	for k, v := range params {
		builder.WriteString("<")
		builder.WriteString(k)
		builder.WriteString(">")
		builder.WriteString(v)
		builder.WriteString("</")
		builder.WriteString(k)
		builder.WriteString(">")
	}
	builder.WriteString("</xml>")
	return builder.String()
}

// ClearPaymentCache 清除支付实例缓存
func ClearPaymentCache(franchiseId int64) {
	delete(paymentInstances, franchiseId)
}

// ClearAllPaymentCache 清除所有支付实例缓存
func ClearAllPaymentCache() {
	paymentInstances = make(map[int64]*payment.Payment)
}

// WxPayOrderStatus 微信支付订单状态结构
type WxPayOrderStatus struct {
	OutTradeNo     string `json:"out_trade_no"`     // 商户订单号
	TransactionId  string `json:"transaction_id"`   // 微信支付订单号
	TradeState     string `json:"trade_state"`      // 交易状态
	TradeStateDesc string `json:"trade_state_desc"` // 交易状态描述
	BankType       string `json:"bank_type"`        // 付款银行
	SuccessTime    string `json:"success_time"`     // 支付完成时间
	Amount         struct {
		Total         int    `json:"total"`          // 订单金额
		PayerTotal    int    `json:"payer_total"`    // 用户支付金额
		Currency      string `json:"currency"`       // 货币类型
		PayerCurrency string `json:"payer_currency"` // 用户支付币种
	} `json:"amount"`
	Payer struct {
		OpenId string `json:"openid"` // 用户标识
	} `json:"payer"`
}

// QueryWxPayOrder 查询微信支付订单状态 - 使用PowerWeChat SDK
func QueryWxPayOrder(franchiseId int64, outTradeNo string) (*WxPayOrderStatus, error) {
	// 获取PowerWeChat支付实例
	paymentApp, err := getPowerWeChatPayment(franchiseId)
	if err != nil {
		return nil, fmt.Errorf("PowerWeChat初始化失败: %v", err)
	}

	ctx := context.Background()

	// 使用PowerWeChat查询订单
	result, err := paymentApp.Order.QueryByOutTradeNumber(ctx, outTradeNo)
	if err != nil {
		return nil, fmt.Errorf("PowerWeChat查询订单失败: %v", err)
	}

	// 转换为统一的订单状态结构
	orderStatus := &WxPayOrderStatus{
		OutTradeNo:     result.OutTradeNo,
		TransactionId:  result.TransactionID,
		TradeState:     result.TradeState,
		TradeStateDesc: result.TradeStateDesc,
		BankType:       result.BankType,
		SuccessTime:    result.SuccessTime,
	}

	if result.Amount != nil {
		orderStatus.Amount.Total = int(result.Amount.Total)
		orderStatus.Amount.PayerTotal = int(result.Amount.PayerTotal)
		orderStatus.Amount.Currency = result.Amount.Currency
		orderStatus.Amount.PayerCurrency = result.Amount.PayerCurrency
	}

	if result.Payer != nil {
		orderStatus.Payer.OpenId = result.Payer.OpenID
	}

	return orderStatus, nil
}

// RefundWxPayOrder 微信支付退款 - 使用PowerWeChat SDK
func RefundWxPayOrder(franchiseId int64, outTradeNo, outRefundNo string, refundAmount, totalAmount int64, reason string) error {
	// 获取PowerWeChat支付实例
	paymentApp, err := getPowerWeChatPayment(franchiseId)
	if err != nil {
		return fmt.Errorf("PowerWeChat初始化失败: %v", err)
	}

	ctx := context.Background()

	// 创建退款请求参数
	refundParams := &refund.RequestRefund{
		OutTradeNo:  outTradeNo,
		OutRefundNo: outRefundNo,
		Reason:      reason,
		Amount: &refund.RefundAmount{
			Refund:   int(refundAmount),
			Total:    int(totalAmount),
			Currency: "CNY",
			From:     []*refund.RefundAmountFrom{},
		},
	}

	// 使用PowerWeChat发起退款
	_, err = paymentApp.Refund.Refund(ctx, refundParams)
	if err != nil {
		return fmt.Errorf("PowerWeChat退款失败: %v", err)
	}

	return nil
}
